/**
 * 开源版本请务必保留此注释头信息，若删除捷码开源〔GEMOS〕官方保留所有法律责任追究！
 * 本软件受国家版权局知识产权以及国家计算机软件著作权保护（登记号：2018SR503328）
 * 不得恶意分享产品源代码、二次转售等，违者必究。
 * Copyright (c) 2020 gemframework all rights reserved.
 * http://www.gemframework.com
 * 版权所有，侵权必究！
 */
package com.gemframework.common.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.gemframework.model.entity.bo.sigar.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hyperic.sigar.CpuInfo;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.NetFlags;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.NetInterfaceStat;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.Swap;
import org.hyperic.sigar.Who;
import org.springframework.stereotype.Component;

/**
 * @Title: GemSigarUtils
 * @Package: com.gemframework.common.utils
 * @Date: 2020-07-30 22:14:37
 * @Version: v1.0
 * @Description: 系统信息采集器
 * @Author: nine QQ 769990999
 * @Copyright: Copyright (c) 2020 wanyong
 * @Company: www.gemframework.com
 */
@Slf4j
@Component
public class GemSigarUtils {

    public static ServerProperty property() throws UnknownHostException {
        Runtime r = Runtime.getRuntime();
        Properties props = System.getProperties();
        InetAddress addr = InetAddress.getLocalHost();
        String ipAddr = addr.getHostAddress();
        Map<String, String> map = System.getenv();
        String userName = map.get("USERNAME");// 获取用户名
        if(userName == null || StringUtils.isBlank(userName)){
            userName = props.getProperty("user.name");
        }
        String userDomain = map.get("USERDOMAIN");// 获取计算机域名
        String computerName = map.get("COMPUTERNAME");// 获取计算机名
        ServerProperty serverProperty = ServerProperty.builder()
                .userName(userName)
                .userHome(props.getProperty("user.home"))
                .userDir(props.getProperty("user.dir"))
                .userDomain(userDomain)
                .computerName(computerName)
                .ipAddr(ipAddr)
                .hostName(addr.getHostName())
                .jvmTotalMemory(r.totalMemory())
                .jvmFreeMemory(r.freeMemory())
                .jvmAvailableProcessors(r.availableProcessors())
                .javaVersion(props.getProperty("java.version"))
                .javaVendor(props.getProperty("java.vendor"))
                .javaVendorURL(props.getProperty("java.vendor.url"))
                .javaHome(props.getProperty("java.home"))
                .jvmSpecificationVersion(props.getProperty("java.vm.specification.version"))
                .jvmSpecificationVendor(props.getProperty("java.vm.specification.vendor"))
                .jvmSpecificationName(props.getProperty("java.vm.specification.name"))
                .jvmVersion(props.getProperty("java.vm.version"))
                .jvmVendor(props.getProperty("java.vm.vendor"))
                .jvmName(props.getProperty("java.vm.name"))
                .javaSpecificationVersion(props.getProperty("java.specification.version"))
                .javaSpecificationVendor(props.getProperty("java.specification.vendor"))
                .javaSpecificationName(props.getProperty("java.specification.name"))
                .javaClassVersion(props.getProperty("java.class.version"))
                .javaClassPath(props.getProperty("java.class.path"))
                .javaLibraryPath(props.getProperty("java.library.path"))
                .javaTmpdirPath(props.getProperty("java.io.tmpdir"))
                .javaExtdirsPath(props.getProperty("java.ext.dirs"))
                .osName(props.getProperty("os.name"))
                .osArch(props.getProperty("os.arch"))
                .osVersion(props.getProperty("os.version"))
                .fileSeparator(props.getProperty("file.separator"))
                .pathSeparator(props.getProperty("path.separator"))
                .lineSeparator(props.getProperty("line.separator"))
                .build();
        return serverProperty;
    }

    public static ServerMemory memory() throws SigarException {
        Sigar sigar = new Sigar();
        Mem mem = sigar.getMem();
        Swap swap = sigar.getSwap();
        ServerMemory serverMemory = ServerMemory.builder()
                .total(mem.getTotal() / (1024L*1024L))
                .used(mem.getUsed()/ (1024L*1024L))
                .free(mem.getFree()/ (1024L*1024L))
                .swapTotal(swap.getTotal()/ (1024L*1024L))
                .swapUsed(swap.getUsed()/ (1024L*1024L))
                .swapFree(swap.getFree()/ (1024L*1024L))
                .build();
        return serverMemory;
    }

    public static List<ServerCPUInfo> cpu() throws SigarException {
        Sigar sigar = new Sigar();
        CpuInfo infos[] = sigar.getCpuInfoList();
        CpuPerc cpuList[] = null;
        cpuList = sigar.getCpuPercList();
        List<ServerCPUInfo> list = new ArrayList<>();
        for (int i = 0; i < infos.length; i++) {// 不管是单块CPU还是多CPU都适用
            CpuInfo info = infos[i];
            ServerCPUInfo cpuInfo = ServerCPUInfo.builder()
                    .index(i + 1)
                    .mhz(info.getMhz())
                    .vendor(info.getVendor())
                    .model(info.getModel())
                    .cacheSize(info.getCacheSize())
                    .used(cpuList[i].getCombined())
                    .userUsed(cpuList[i].getUser())
                    .sysUsed(cpuList[i].getSys())
                    .wait(cpuList[i].getWait())
                    .error(cpuList[i].getNice())
                    .free(cpuList[i].getIdle())
                    .build();
            list.add(cpuInfo);
        }
        return list;
    }

    public static ServerOSInfo os() {
        OperatingSystem OS = OperatingSystem.getInstance();
        ServerOSInfo serverOSInfo = ServerOSInfo.builder()
                .arch(OS.getArch())
                .cpuEndian(OS.getCpuEndian())
                .dataModel(OS.getDataModel())
                .description(OS.getDescription())
                .vendor(OS.getVendor())
                .vendorCodeName(OS.getVendorCodeName())
                .vendorName(OS.getVendorName())
                .vendorVersion(OS.getVendorVersion())
                .version(OS.getVersion())
                .build();
        return serverOSInfo;
    }

    public static List<ServerWhoInfo> who() throws SigarException {
        Sigar sigar = new Sigar();
        Who who[] = sigar.getWhoList();
        List<ServerWhoInfo> list = new ArrayList<>();
        if (who != null && who.length > 0) {
            for (int i = 0; i < who.length; i++) {
                Who _who = who[i];
                ServerWhoInfo serverWhoInfo = ServerWhoInfo.builder()
                        .id(i+1)
                        .console(_who.getDevice())
                        .host(_who.getHost())
                        .userName(_who.getUser())
                        .build();
                list.add(serverWhoInfo);
            }
        }
        return list;
    }

    public static List<ServerDiskInfo> file() throws SigarException {
        List<ServerDiskInfo> list = new ArrayList<>();
        Sigar sigar = new Sigar();
        FileSystem fslist[] = sigar.getFileSystemList();
        if (fslist != null && fslist.length > 0) {
            for (int i = 0; i < fslist.length; i++) {
                log.info("分区的盘符索引" + i);
                FileSystem fs = fslist[i];
                FileSystemUsage usage = null;
                usage = sigar.getFileSystemUsage(fs.getDirName());
                double total = 0L;
                double free = 0L;
                double avail = 0L;
                double used = 0L;
                double usePercent = 0;
                switch (fs.getType()) {
                    case 0: // TYPE_UNKNOWN ：未知
                        break;
                    case 1: // TYPE_NONE
                        break;
                    case 2: // TYPE_LOCAL_DISK : 本地硬盘
                        total = usage.getTotal();
                        free = usage.getFree();
                        avail = usage.getAvail();
                        used = usage.getUsed();
                        usePercent = usage.getUsePercent()*100D;
                        break;
                    case 3:// TYPE_NETWORK ：网络
                        break;
                    case 4:// TYPE_RAM_DISK ：闪存
                        break;
                    case 5:// TYPE_CDROM ：光驱
                        break;
                    case 6:// TYPE_SWAP ：页面交换
                        break;
                }
                ServerDiskInfo serverDiskInfo = ServerDiskInfo.builder()
                        .devId(i+1)
                        .devName(fs.getDevName())
                        .dirName(fs.getDirName())
                        .devFlag(fs.getFlags())
                        .sysType(fs.getSysTypeName())
                        .devType(fs.getTypeName())
                        .fileType(fs.getType())
                        .total(total)
                        .free(free)
                        .avail(avail)
                        .used(used)
                        .usePercent(usePercent)
                        .reads(usage.getDiskReads())
                        .writes(usage.getDiskWrites())
                        .build();
                list.add(serverDiskInfo);
            }
        }
        return list;
    }

    public static List<ServerNetwork> net() throws SigarException {
        List<ServerNetwork> list = new ArrayList<>();
        Sigar sigar = new Sigar();
        String ifNames[] = sigar.getNetInterfaceList();
        for (int i = 0; i < ifNames.length; i++) {
            String name = ifNames[i];
            NetInterfaceConfig ifconfig = sigar.getNetInterfaceConfig(name);
            NetInterfaceStat ifstat = sigar.getNetInterfaceStat(name);
            if (NetFlags.LOOPBACK_ADDRESS.equals(ifconfig.getAddress()) || (ifconfig.getFlags() & NetFlags.IFF_LOOPBACK) != 0
                    || NetFlags.NULL_HWADDR.equals(ifconfig.getHwaddr())) {
                continue;
            }
            ServerNetwork serverNetwork = ServerNetwork.builder()
                    .ethernetName(name)
                    .ipAddress(ifconfig.getAddress())
                    .netmask(ifconfig.getNetmask())
                    .broadcast(ifconfig.getBroadcast())
                    .mac(ifconfig.getHwaddr())
                    .description(ifconfig.getDescription())
                    .type(ifconfig.getType())
                    .rxPackets(ifstat.getRxPackets())
                    .txPackets(ifstat.getTxPackets())
                    .rxBytes(ifstat.getRxBytes())
                    .txBytes(ifstat.getTxBytes())
                    .rxErrors(ifstat.getRxErrors())
                    .txErrors(ifstat.getTxErrors())
                    .rxDropped(ifstat.getRxDropped())
                    .txDropped(ifstat.getTxDropped())
                    .build();
            if ((ifconfig.getFlags() & 1L) <= 0L) {
                log.info("!IFF_UP...skipping getNetInterfaceStat");
                continue;
            }
            list.add(serverNetwork);
        }
        return list;
    }

    public static void main(String[] args) throws SigarException {
        //设置sigar依赖包路径
        System.setProperty("org.hyperic.sigar.path", "/aaa/sigar");
        List<ServerDiskInfo> list = file();
        log.info("=="+list);
    }
}